package org.ands.client;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.ands.client.aad.ContentsRetrieverAAD;
import org.ands.client.aad.ContentsRetrieverTestAAD;
import org.ands.client.aad.RifCsSchemaRulesAAD;
import org.ands.client.aims.ContentsRetrieverAIMS;
import org.ands.client.aims.ContentsRetrieverTestFileAIMS;
import org.ands.client.aims.ContentsRetrieverTestUriAIMS;
import org.ands.client.aims.RifCsSchemaRulesAIMS;
import org.ands.client.ala.ContentsRetrieverALA;
import org.ands.client.ala.ContentsRetrieverALASpatial;
import org.ands.client.ala.ContentsRetrieverALASpecies;
import org.ands.client.ala.RifCsSchemaRulesALA;
import org.ands.client.aodn.ContentsRetrieverAODN;
import org.ands.client.aodn.ContentsRetrieverTestFileAODN;
import org.ands.client.aodn.ContentsRetrieverTestUriAODN;
import org.ands.client.aodn.RifCsSchemaRulesAODN;
import org.ands.client.eatlas.RifCsSchemaRulesEATLAS;
import org.ands.client.test.oai.ContentsRetrieverTestOAI;
import org.ands.client.test.oai.ContentsRetrieverTestUriTestOAI;
import org.ands.data.IClientContentsRetriever;
import org.ands.rifcs.RifCsSchemaRulesCommon;
import org.ands.xml.ISchemaRules;

// TODO: Auto-generated Javadoc
/**
 * A factory for creating Topic objects.
 */
public class TopicFactory {
	
	/**
	 * The Enum Topic.
	 */
	public enum Topic {
		
			/** The ala spatial. */
			ALA_SPATIAL, 
			/** The ala species. */
			ALA_SPECIES,
			/** The ala data resources data providers. */
			ALA_DATA_RESOURCES_DATA_PROVIDERS, 
			/** The aad. */
			AAD,
			/** The aad test. */
			AAD_TEST,
			/** e-Atlas. */
			E_ATLAS, 
			/** Australian Institute of Marine Science (AIMS) */
			AIMS_OAIPMH, 
			AIMS_FILE, 
			AIMS_URI, 
			/** Australian Ocean Data Network (AODN) */
			AODN_OAIPMH, 
			AODN_FILE, 
			AODN_URI,
			/** Test any OAI implementation */
			TEST_OAIPMH, 
			TEST_URI;
	}
	
	public static final Map<Topic, String> _topicNameMap;
	static {
		Map<Topic, String> newMap = new HashMap<Topic, String>();
		newMap.put(Topic.ALA_SPATIAL, "ALA.SPATIAL");
		newMap.put(Topic.ALA_SPECIES, "ALA_SPECIES");
		newMap.put(Topic.ALA_DATA_RESOURCES_DATA_PROVIDERS, "ALA_DATA_RESOURCES_DATA_PROVIDERS");
		newMap.put(Topic.AAD, "AAD");
		newMap.put(Topic.AAD_TEST, "AAD_TEST");
		newMap.put(Topic.E_ATLAS, "E_ATLAS");
		newMap.put(Topic.AIMS_OAIPMH, "AIMS_OAIPMH"); 
		newMap.put(Topic.AIMS_FILE, "AIMS_FILE"); 
		newMap.put(Topic.AIMS_URI, "AIMS_URI"); 
		newMap.put(Topic.AODN_OAIPMH, "AODN_OAIPMH"); 
		newMap.put(Topic.AODN_FILE, "AODN_FILE"); 
		newMap.put(Topic.AODN_URI, "AODN_URI");
		newMap.put(Topic.TEST_OAIPMH, "TEST_OAIPMH"); 
		newMap.put(Topic.TEST_URI, "TEST_URI");
		_topicNameMap = Collections.unmodifiableMap(newMap);
	}
	
	
	
	/**
	 * Gets the topic retriever.
	 *
	 * @param topic the topic
	 * @return the topic retriever
	 * @throws Exception the exception
	 */
	public static IClientContentsRetriever getTopicRetriever(final Topic topic) throws Exception {
		
		switch(topic) {
			case ALA_SPATIAL :
				return new ContentsRetrieverALASpatial();
			case ALA_SPECIES :
				return new ContentsRetrieverALASpecies();
			case ALA_DATA_RESOURCES_DATA_PROVIDERS :
				return new ContentsRetrieverALA();
			case AAD :
				return new ContentsRetrieverAAD();
			case AAD_TEST :
				return new ContentsRetrieverTestAAD();
			case AIMS_OAIPMH:
				return new ContentsRetrieverAIMS();
			case AIMS_FILE:
				return new ContentsRetrieverTestFileAIMS();
			case AIMS_URI:
				return new ContentsRetrieverTestUriAIMS();
			case AODN_OAIPMH:
				return new ContentsRetrieverAODN();
			case AODN_FILE:
				return new ContentsRetrieverTestFileAODN();
			case AODN_URI:
				return new ContentsRetrieverTestUriAODN();
			case TEST_OAIPMH:
				return new ContentsRetrieverTestOAI();
			case TEST_URI:
				return new ContentsRetrieverTestUriTestOAI();
			case E_ATLAS:
				assert(false);
				throw new Exception("Not yet implemented - retriever for topic "+topic);
		}
		
		assert(false);
		throw new Exception("Unable to handle topic "+topic);
	}
	
	/**
	 * Gets the topic rifcs schema rules.
	 *
	 * @param topic the topic
	 * @return the topic rifcs schema rules
	 * @throws Exception the exception
	 */
	public static ISchemaRules getTopicRifcsSchemaRules(final Topic topic) throws Exception {
		
		switch(topic) {
		case ALA_SPATIAL :
			return new RifCsSchemaRulesALA();
		case ALA_SPECIES :
			return new RifCsSchemaRulesALA();
		case ALA_DATA_RESOURCES_DATA_PROVIDERS :
			return new RifCsSchemaRulesALA();
		case AAD :
		case AAD_TEST :
			return new RifCsSchemaRulesAAD();
		case AIMS_OAIPMH :
		case AIMS_FILE :
		case AIMS_URI :
			return new RifCsSchemaRulesAIMS();
		case AODN_OAIPMH :
		case AODN_FILE :
		case AODN_URI :
			return new RifCsSchemaRulesAODN();
		case E_ATLAS:
			return new RifCsSchemaRulesEATLAS();
		case TEST_OAIPMH:
		case TEST_URI:
			return new RifCsSchemaRulesCommon();
		}

		assert(false);
		throw new Exception("Unable to handle topic "+topic);
	}
	
	/**
	 * Gets the topic rifcs schema rules.
	 *
	 * @param topic the topic
	 * @return the topic rifcs schema rules
	 * @throws Exception the exception
	 */
	public static Topic getTopicFromString(final String stringTopic) throws Exception {
		
		assert(_topicNameMap != null);
		assert(!_topicNameMap.isEmpty());
		for(Map.Entry<Topic, String> entry : _topicNameMap.entrySet()){
			if(entry.getValue().equals(stringTopic)){
				System.out.println("Found topic for string topic "+stringTopic);
				return entry.getKey();
			}
		}
		
		assert(false);
		throw new Exception("Unable to find topic called: "+stringTopic);
	}

	
}

